﻿using CSharpStrengthenTeach;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpInheritTeach
{
    /// <summary>
    /// 面向对象中一个非常重要原则：开-闭原则
    /// 
    /// 开放：增加类（需要变化）
    /// 封闭：修改类
    /// 
    /// 继承多态
    /// 第一：子类对象作为方法的返回值
    /// 第二：父类作为方法的参数类型
    /// 
    /// 
    /// 多态简要总结：为了更好的响应用户需求变化所带来的程序重新修改的影响
    /// 
    /// 
    /// 4.虚方法（父类可以有自己的“默认”实现） 抽象方法没有实现
    /// 子类自己想实现，那就是对父类方法的“重写”
    /// 虚方法不具有强制性，不需要子类必须实现
    /// 
    /// 总结：虚方法也可以实现多态
    /// 
    /// 选择：如果不需要父类有默认实现，则选用抽象方法，反之，选择虚方法
    /// 
    /// 
    /// 5.new关键字（覆盖父类的同名方法）
    /// 特殊性：在子类方法中使用new关键字，可以实现对父类“同名方法”的覆盖
    /// 使用场景：我们后面学习相关的控件的二次开发的时候，比如重新定义第一个事件就可以用这个方法
    /// 
    /// </summary>
    internal class Program
    {
        static void Main(string[] args)
        {
            Test11();
            Console.ReadLine();
        }

        #region 继承基础
        static void Test1()
        {
            Teacher teacher = new Teacher();

            teacher.Name = "Test1";

            teacher.Gender = "男";

            teacher.Dowork();
            teacher.Reset();

            teacher.Company = "hhhh";
            teacher.Show();
        }

        static void Test2()
        {
            Teacher teacher = new Teacher("ttt","女","教育");

            teacher.Dowork();
            teacher.Reset();
            teacher.Show();
        }

        static void Test3()
        {
            Person person = new Person();
            
            //使用protectd修饰的成员（属性，方法） 通过“对象”是无法使用的
        }
        #endregion

        #region 基础进阶
        static void Test5()
        {
            //抽象类不能直接实例化
            //NewPerson newPerson = new NewPerson();  

            //抽象类中是可以有普通的静态方法
            NewPerson.TestMedths(); 
        }

        static void Test6()
        {
            NewTeacher newTeacher = new NewTeacher();
            newTeacher.Play();

            Doctor doctor = new Doctor();
            doctor.Play();
        }

        static void Test7()
        {
            NewTeacher newTeacher = new NewTeacher();
            Doctor doctor = new Doctor();

            newTeacher.Play();
            doctor.Play();
        }

        static void Test8()
        {
           /* NewTeacher newTeacher = new NewTeacher();
            Doctor doctor = new Doctor();

            newTeacher.Play();
            doctor.Play();*/

            // 使用父类变量来接收子类对象
            NewPerson newPerson = new NewTeacher();
            newPerson.Play();

            newPerson = new Doctor();
            newPerson.Play();

            //将子类对象做一个封装
            NewPerson newPerson2 = GetPerson();
            newPerson2.Play();
        }

        static void Test9()
        {
            //将子类对象做一个封装（子类对象可以根据需要返回，而此地方不需要做任何改变）
            NewPerson newPerson2 = GetPerson();
            newPerson2.Play();

            Console.WriteLine("-----------------------");

            Test9(new ThirdPerson());
            Test9(new Doctor());

            Console.WriteLine("-----------------------");

            Test10(new ThirdPerson());
            Test10(new Doctor());
        }

        static void Test10(NewPerson p)
        {
            p.Listen();
            p.Play();
        }

        /// <summary>
        /// 父类作为方法的返回值
        /// </summary>
        /// <returns></returns>
        static NewPerson GetPerson()
        {
            return new ThirdPerson();
        }

        /// <summary>
        /// 父类作为方法的参数类型
        /// </summary>
        /// <param name="p"></param>
        static void Test9(NewPerson p)
        {
            p.Play();
        }

        static void Test11()
        {
            Doctor newPerson = new Doctor();
            newPerson.Dowork();
        }

        #endregion 
    }
}
